﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using System.Windows.Input;
using SqlMiM.Common.ViewModel;
using SqlMiM.Common.Commands;
using System.Collections.ObjectModel;
using System.Diagnostics;
using SqlMiM.SqlIndexes.Core;
using System.Windows.Threading;
using System.Collections;
using System.Windows;
using System.Windows.Data;
using SqlMiM.SqlIndexes.ViewModel;
using SqlMiM.Common.Core;
using SqlMiM.Common.Model;
using SqlMiM.SqlIndexes.Model;
using SqlMiM.Common.Framework.Configuration;
using SqlMiM.Common;
using SqlMiM.SqlIndexes.Options;
using MvvmFoundation.Wpf;

namespace SqlMiM.SqlIndexes.UnusedIndexes
{
    public class ViewModel : ObservableObject
    {
        private BackgroundWorker bgw;
        private BackgroundWorker bgwGetUnusedIndexse;
        private ObservableCollection<DatabaseView> databases;
        private CollectionViewSource unusedIndexes;
        private ConfigurationObject configurationObject;
        private RelayCommand<SelectType> selectElements;
        private RelayCommand getUnusedIndexesCommand;

        public CollectionViewSource UnusedIndexesView
        {
            get { return unusedIndexes; }
            set
            {
                unusedIndexes = value;
                this.RaisePropertyChanged("UnusedIndexesView");
            }
        }


        public ObservableCollection<DatabaseView> Databases
        {
            get { return databases; }
            set
            {
                databases = value;
                this.RaisePropertyChanged("Databases");
            }
        }


        /// <summary>
        /// 
        /// </summary>
        public ICommand SelectElements
        {
            get
            {
                if (selectElements == null)
                {
                    selectElements = new RelayCommand<SelectType>(param => this.SelectUnselectReverse(param));

                }
                return selectElements;
            }
        }


        /// <summary>
        /// 
        /// </summary>
        public ICommand SelectUnusedIndexesCommand
        {
            get
            {
                if (getUnusedIndexesCommand == null)
                {
                    getUnusedIndexesCommand = new RelayCommand(this.GetUnusedIndexes);

                }
                return getUnusedIndexesCommand;
            }
        }

        private void GetUnusedIndexes()
        {

            ObservableCollection<UnusedIndexView> razCol = this.UnusedIndexesView.Source as ObservableCollection<UnusedIndexView>;
            razCol.Clear();

            bgwGetUnusedIndexse = new BackgroundWorker();
            bgwGetUnusedIndexse.WorkerReportsProgress = true;

            bgwGetUnusedIndexse.DoWork += (sender, args) => 
            { 
                if (this.Databases != null)
                    this.internalGetUnusedIndexes(); 
            };

            bgwGetUnusedIndexse.ProgressChanged += (sender, args) =>
            {
                List<UnusedIndex> lst = args.UserState as List<UnusedIndex>;

                if (lst == null) return;

                ObservableCollection<UnusedIndexView> col = this.UnusedIndexesView.Source as ObservableCollection<UnusedIndexView>;

                foreach (var fi in lst)
                    col.Add(new UnusedIndexView(fi));
            };

            bgwGetUnusedIndexse.RunWorkerCompleted += (sender, args) =>
            {
                //this.Databases = new ObservableCollection<UnusedDatabaseView>(args.Result as List<UnusedDatabaseView>);

                //this.UnusedIndexesView.Source = args.Result as List<UnusedIndexInfoView>;
                //this.UnusedIndexesView.GroupDescriptions.Add(new PropertyGroupDescription("Index_database")); 
            };

            bgwGetUnusedIndexse.RunWorkerAsync();

        }

        private void internalGetUnusedIndexes()
        {
            if (this.Databases == null || this.Databases.Count == 0)
                return;

            foreach (var db in this.Databases)
            {
                if (db.IsChecked)
                {
                    var lstFrags = IndexesService.Current.GetUnusedIndexes(db.Database);

                    bgwGetUnusedIndexse.ReportProgress(0, lstFrags);
                }
            }
        }




        private void SelectUnselectReverse(SelectType type)
        {
            if (this.Databases == null || this.Databases.Count == 0)
                return;

            // Select all
            if (type == SelectType.SelectAll)
            {
                foreach (var lv in this.Databases)
                    lv.IsChecked = true;
            }
            // UnSelect all
            else if (type == SelectType.UnselectAll)
            {
                foreach (var lv in this.Databases)
                    lv.IsChecked = false;
            }
            // Reverse
            else if (type == SelectType.ReverseSelection)
            {
                foreach (var lv in this.Databases)
                    lv.IsChecked = !lv.IsChecked;
            }
        }



        public ViewModel()
        {
            this.Databases = new ObservableCollection<DatabaseView>();
            this.UnusedIndexesView = new CollectionViewSource();
            this.UnusedIndexesView.Source = new ObservableCollection<UnusedIndexView>();
            this.UnusedIndexesView.GroupDescriptions.Add(new PropertyGroupDescription("UnusedIndex.DatabaseName"));

            this.configurationObject = Context.Current.Configuration[IndexOptionsPage.NAME];

            this.Load();
        }



        internal void Load()
        {
            this.Databases.Clear();
            (this.UnusedIndexesView.Source as ObservableCollection<UnusedIndexView>).Clear();

            bgw = new BackgroundWorker();

            bgw.DoWork += (sender, args) =>
            {
                bool includeSysTables = (bool)this.configurationObject.GetProperty(IndexOptionsPage.GET_SYSTEM_TABLES_PROPERTY, IndexOptionsPage.GET_SYSTEM_TABLES_DEFAULT_VALUE);

                args.Result = DatabasesService.Current.GetDatabases(includeSysTables);
            };

            bgw.RunWorkerCompleted += (sender, args) =>
            {
                var dbs = args.Result as List<Database>;

                if (dbs == null) return;


                foreach (var db in dbs)
                    this.Databases.Add(new DatabaseView(db));

            };

            bgw.RunWorkerAsync();
        }
    }

    public enum SelectType
    {
        SelectAll,
        UnselectAll,
        ReverseSelection,
    }


}
